//+------------------------------------------------------------------+
//|                       TreeNode.mqh 二叉树节点类头文件             |
//|                版权所有 2000-2025, MetaQuotes Ltd.              |
//|                        官方网址: https://www.mql5.com            |
//+------------------------------------------------------------------+
#include <Object.h>  // 引入 CObject 基类头文件，CTreeNode 继承自 CObject
//+------------------------------------------------------------------+
//| CTreeNode 类                                                      |
//| 功能：二叉树节点基类，作为 CTree 平衡二叉树的基本组成单元          |
//| 核心特性：                                                       |
//|  1. 维护节点间的关联关系（父节点、左子节点、右子节点指针）         |
//|  2. 提供树平衡计算逻辑（节点自身及左右分支的平衡值）              |
//|  3. 支持节点数据的文件序列化/反序列化，配合树结构持久化           |
//| 继承关系：派生自 CObject 基类，需重写 Compare 方法定义节点比较规则 |
//+------------------------------------------------------------------+
class CTreeNode : public CObject
  {
private:
   CTreeNode        *m_p_node;             // 指向父节点的指针（上一级节点）
   CTreeNode        *m_l_node;             // 指向左子节点的指针（值小于当前节点）
   CTreeNode        *m_r_node;             // 指向右子节点的指针（值大于当前节点）
   int               m_balance;            // 当前节点的平衡值（左右分支高度差相关）
   int               m_l_balance;          // 左分支的平衡值（左子树高度）
   int               m_r_balance;          // 右分支的平衡值（右子树高度）

public:
   /**
    * @brief 构造函数：初始化 CTreeNode 节点实例
    * @details 初始化所有节点指针为 NULL（无关联节点），平衡值均为 0（默认无高度）
    */
                     CTreeNode(void);

   /**
    * @brief 析构函数：销毁 CTreeNode 节点实例
    * @details 递归删除左子节点和右子节点（释放动态分配的内存），避免内存泄漏
    */
                    ~CTreeNode(void);

   //--- 私有成员变量访问方法（读写）
   /**
    * @brief 获取当前节点的父节点指针
    * @return CTreeNode* - 父节点指针，无父节点（根节点）返回 NULL
    */
   CTreeNode*        Parent(void)           const { return(m_p_node);    }

   /**
    * @brief 设置当前节点的父节点指针
    * @param node [in] 父节点指针（需确保为当前树中的有效节点）
    */
   void              Parent(CTreeNode *node)      { m_p_node=node;       }

   /**
    * @brief 获取当前节点的左子节点指针
    * @return CTreeNode* - 左子节点指针，无左子节点返回 NULL
    */
   CTreeNode*        Left(void)             const { return(m_l_node);    }

   /**
    * @brief 设置当前节点的左子节点指针
    * @param node [in] 左子节点指针（需确保值小于当前节点，符合二叉树规则）
    */
   void              Left(CTreeNode *node)        { m_l_node=node;       }

   /**
    * @brief 获取当前节点的右子节点指针
    * @return CTreeNode* - 右子节点指针，无右子节点返回 NULL
    */
   CTreeNode*        Right(void)            const { return(m_r_node);    }

   /**
    * @brief 设置当前节点的右子节点指针
    * @param node [in] 右子节点指针（需确保值大于当前节点，符合二叉树规则）
    */
   void              Right(CTreeNode *node)       { m_r_node=node;       }

   /**
    * @brief 获取当前节点的平衡值（整体高度）
    * @return int - 平衡值，等于左右分支中较高者的高度 + 1
    */
   int               Balance(void)          const { return(m_balance);   }

   /**
    * @brief 获取左分支的平衡值（左子树高度）
    * @return int - 左分支高度，无左子树返回 0
    */
   int               BalanceL(void)         const { return(m_l_balance); }

   /**
    * @brief 获取右分支的平衡值（右子树高度）
    * @return int - 右分支高度，无右子树返回 0
    */
   int               BalanceR(void)         const { return(m_r_balance); }

   //--- 对象类型识别方法
   /**
    * @brief 获取当前节点对象的类型标识（用于区分其他 CObject 派生类）
    * @return int - 类型标识，固定返回 0x8888（MQL5 二叉树节点类专属标识）
    */
   virtual int       Type(void) const { return(0x8888); }

   //--- 节点控制方法
   /**
    * @brief 刷新当前节点及所有子节点的平衡值（高度计算）
    * @details 递归计算左分支和右分支的高度，更新当前节点的平衡值（max(左高, 右高) + 1）
    * @return int - 更新后的当前节点平衡值
    */
   int               RefreshBalance(void);

   /**
    * @brief 根据目标节点的值获取下一个应访问的子节点（左/右）
    * @details 基于当前节点与目标节点的比较结果（通过 CObject::Compare 方法）决定方向：
    *          Compare 返回值 > 0 → 目标节点值更小 → 应访问左子节点；
    *          否则 → 目标节点值更大 → 应访问右子节点
    * @param node [in] 目标节点指针（需确保指针有效）
    * @return CTreeNode* - 下一个应访问的子节点指针（左或右），无对应子节点返回 NULL
    */
   CTreeNode        *GetNext(const CTreeNode *node);

   //--- 文件操作相关方法（节点及子节点数据序列化/反序列化）
   /**
    * @brief 将当前节点及所有子节点的数据写入指定文件（递归操作）
    * @details 写入顺序：先写左子节点标记（'L' 表示存在，'X' 表示不存在）及数据，
    *          再写当前节点数据（调用 CObject::Save 方法），最后写右子节点标记及数据
    * @param file_handle [in] 已打开的文件句柄（需包含写入权限，建议用 FILE_BIN 模式）
    * @return bool - 操作结果：true 表示当前节点及所有子节点均写入成功，false 表示失败
    */
   bool              SaveNode(const int file_handle);

   /**
    * @brief 从指定文件读取数据，重建当前节点及所有子节点（递归操作）
    * @details 读取顺序：先读左子节点标记，若为 'L' 则创建左子节点并递归读取其数据，
    *          再读当前节点数据（调用 CObject::Load 方法），最后读右子节点标记并处理
    * @param file_handle [in] 已打开的文件句柄（需包含读取权限，建议用 FILE_BIN 模式）
    * @param main [in] 父节点指针（用于设置当前节点的 Parent 关联）
    * @return bool - 操作结果：true 表示当前节点及所有子节点均读取成功，false 表示失败
    */
   bool              LoadNode(const int file_handle,CTreeNode *main);

protected:
   /**
    * @brief 创建当前节点类的实例（内部使用，用于文件读取时重建节点）
    * @details 基类默认返回 NULL，需在派生类中重写以创建具体节点实例（如返回 new CMyTreeNode）
    *          配合 LoadNode 方法使用，确保从文件读取时能正确创建节点对象
    * @return CTreeNode* - 新创建的节点实例指针；基类默认返回 NULL，必须在派生类中重写
    */
   virtual CTreeNode *CreateSample(void) { return(NULL); }
  };
//+------------------------------------------------------------------+